/****************************************************************
 ** Product  :   HP Subscriber Network Application Policy
 ** Module   :   gr-manager
 ** Date: Apr 10, 2015               
 ** Author: Joey Yi
 ** (C) Copyright 2015, Hewlett-Packard Company, All Rights Reserved.
 ** This software is the proprietary information of HP, Inc.  
 ** Use is subject to license terms.
 *****************************************************************
 ** Description:   
 **     Check the DB status and start the DB cluster by specific mode.
 **    
 ****************************************************************/
package com.hp.snap.gr.action.impl;

import com.hp.snap.gr.exception.ActionException;
import com.hp.snap.gr.model.Database;
import com.hp.snap.gr.model.jaxb.ActionType;
import com.hp.snap.gr.model.jaxb.GeneralActionType;
import com.hp.snap.gr.model.jaxb.ParameterType;
import com.hp.snap.gr.utils.Constants;
import com.hp.snap.gr.utils.RESTfulUtils;
import com.hp.snap.gr.utils.Utils;
import com.hp.snap.gr.utils.VoltDBController;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Map;

/**
 * 
 * Check the DB status and start the DB cluster by specific mode.
 * 
 * There are three parameters need to be configured: DB_INSTANCE_NAME, START_MODE and IS_RECOVER.
 * DB_INSTANCE_NAME: The VoltDB DB instance name, such as: spr_db, session_db, lb_db.
 * STRAT_MODE: The start mode of DB cluster, optional values: MASTER or REPLICA;
 * IS_RECOVER: For start a DB cluster to MASTER mode, whether recover the DB or not; default value is 'false'
 * 
 * <P>
 * Version: 3.3 <br>
 * Author: Joey Yi Date: Apr 10, 2015
 * 
 * </P>
 * 
 **/
public class CheckVoltDBStatusAndStartActionHandler extends AbstractActionHandler {
    private static Logger logger = LoggerFactory.getLogger(CheckVoltDBStatusAndStartActionHandler.class);

    @Override
    public void execute(ActionType action, Map<String, Object> actionPlanInputs,
                        Map<String, Object> actionPlanOutputs) throws ActionException {

        GeneralActionType actionType = (GeneralActionType) action;
        List<ParameterType> parameterTypes = actionType.getParameter();
        Map<String, String> parameterMap = Utils.contructParamMap(parameterTypes);

        /**
         * get the db instance name, which should be configured in: /SNAP/GR/<DEPLOY_NAME>/VOLTDB/<DB_INSTANCE_NAME>, e.g.
         * /SNAP/GR/Site_A1/VOLTDB/session_db]
         */
        String dbInstName = parameterMap.get("DB_INSTANCE_NAME");
        if (StringUtils.isEmpty(dbInstName)) {
            throw new ActionException("The parameter [DB_INSTANCE_NAME] should be configured!");
        }

        if (logger.isTraceEnabled()) {
            logger.trace("[CheckVoltDBStatusAndStartActionHandler] input parameterMap=" + parameterMap.toString());
        }

        // get the DB cluster starting mode: MASTER or REPLICA
        String startMode = parameterMap.get("START_MODE");

        if (logger.isTraceEnabled()) {
            logger.trace("startMode=" + parameterMap.get("START_MODE"));
        }

        if (StringUtils.isEmpty(startMode) || (!Constants.VDB_MODE_MASTER.equals(startMode) && !Constants.VDB_MODE_REPLICA.equals(startMode))) {
            throw new ActionException("The parameter [START_MODE] should be correct configured! The optional values are: MASTER or REPLICA.");
        }

        boolean isRecover = false;

        if (parameterMap.containsKey("IS_RECOVER")) {
            String isRecoverStr = parameterMap.get("IS_RECOVER");
            if (isRecoverStr == null || (!isRecoverStr.equalsIgnoreCase("true") && !isRecoverStr.equalsIgnoreCase("false"))) {
                throw new ActionException("The parameter[IS_RECOVER] is not configured properly.");
            }
            if (isRecoverStr.equalsIgnoreCase("true")) {
                isRecover = true;
            }
        }


        // find out the target database profile
        Database database = RESTfulUtils.getVoltDBDatabase(dbInstName);

        if (database == null) {
            throw new ActionException("The database instance is not exist: " + dbInstName);
        }

        String status = database.getStatus();
        boolean replica = database.isReplica();

        if (Constants.VDB_STATUS_ONLINE.equals(status)) {

            logger.info("The DB Instance [{}] already running in [{}] mode!", dbInstName, replica ? Constants.VDB_MODE_REPLICA : Constants.VDB_MODE_MASTER);

        } else if (Constants.VDB_STATUS_OFFLINE.equals(status)) {

            if (Constants.VDB_MODE_REPLICA.equals(startMode)) {
                if (logger.isDebugEnabled()) {
                    logger.debug("starting db name={" + database.getName() + "} with replica mode");
                }

                VoltDBController.startDatabase(database, true);

            } else {

                if (logger.isDebugEnabled()) {
                    logger.debug("starting db name={" + database.getName() + "} with master mode");
                }

                if (!isRecover) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("starting db name={" + database.getName() + "} with master mode");
                    }
                    VoltDBController.startDatabase(database, false);
                } else {
                    if (logger.isDebugEnabled()) {
                        logger.debug("recovering db name={" + database.getName() + "} with replica mode");
                    }
                    VoltDBController.recoverDatabase(database);
                }
            }

            logger.info("{} the DB Instance successfully, Name: {}, ID: {}", new Object[]{isRecover ? "Recover" : "Start", dbInstName, database.getId()});

        } else {
            logger.warn("The database is in status [{}], and do not process!", status);
        }
    }
}
